package com.shyroke.daydayzhuanjob;

import cn.hutool.core.date.DateUtil;
import com.shyroke.daydayzhuanapi.constant.RedisKeyPrefix;
import com.shyroke.daydayzhuanapi.entity.ProjectEntity;
import com.shyroke.daydayzhuanapi.entity.SubjectEntity;
import com.shyroke.daydayzhuandao.respository.ProjectRepository;
import com.shyroke.daydayzhuandao.respository.SubjectRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 类名 ：文章定时器，用于更新文章阅读量
 * 用法 ：
 * 创建人 ： shyroke
 * 时间：2019/2/20 13:49
 */
@Component
public class ArticleJob {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private ProjectRepository projectRepository;
    @Autowired
    private SubjectRepository subjectRepository;


    /**
     * 每小时执行更新阅读量任务
     */
    @Scheduled(initialDelay = 1000*60*60, fixedRate = 1000*60*60)
    public void updateReadCount()  {
        logger.info("=====每小时执行更新阅读量任务开始=====");
        String keyPre = RedisKeyPrefix.PROJECTCOUNT+":viewCount:*";
        Set<String> keys = redisTemplate.keys(keyPre);
        //文章ID集合
        List<Integer> idList = new ArrayList<>();
        //文章ID和阅读量map
        Map<Integer,Integer> idNCountMap= new HashMap<>();
        //文章ID和APP阅读量map
        Map<Integer,Integer> appIdNCountMap= new HashMap<>();
        int hour = DateUtil.thisHour(true);
        if(!CollectionUtils.isEmpty(keys)){
            for (String key : keys) {
                Integer count = (Integer)redisTemplate.opsForValue().get(key);
                //等于0就不用更新
                if(count == null || count == 0){
                    continue;
                }
                //从key中解析获取文章ID
                String[] split = key.split(":");
                Integer articleId = Integer.valueOf(split[split.length-1]);
                idList.add(articleId);
                idNCountMap.put(articleId,count);
                String appKey = RedisKeyPrefix.PROJECTCOUNT+":viewCount:app:"+articleId;
                Integer appCount = (Integer)redisTemplate.opsForValue().get(appKey);
                appIdNCountMap.put(articleId, appCount);
                //将redis的文章ID置空
                redisTemplate.opsForValue().set(key,count == null ? 0 : (count-count));
                redisTemplate.opsForValue().set(appKey,appCount == null ? 0 : (appCount-appCount));
            }
            for (Integer id : idNCountMap.keySet()) {
                Integer count = idNCountMap.get(id);
                Integer appCount = appIdNCountMap.get(id);
                Optional<ProjectEntity> optionalProject = projectRepository.findById(id);

                if (optionalProject.isPresent()) {
                    ProjectEntity project = optionalProject.get();
                    project.setReadMount(project.getReadMount()+count);
                    if(hour == 1) {
                        //1点钟是重置当日阅读量和app当日阅读量的时间点
                        project.setTodayReadCount(0);
                        project.setTodayAppReadCount(0);
                    }else {
                        project.setTodayReadCount(project.getTodayReadCount()+count);
                        if(appCount != null) {
                            project.setTodayAppReadCount(project.getTodayAppReadCount()+appCount);
                        }
                    }

                    projectRepository.save(project);
                }
            }
        }
        logger.info("=====每小时执行更新阅读量任务结束=====");
    }

    /**
     * 更新文章每日阅读量
     */
    @Scheduled(cron = "0 0 1 * * ?")
    public void updateTodayReadCount() {
        logger.info("更新文章每日阅读量开始");
        PageRequest page = PageRequest.of(0, 100, Sort.Direction.DESC, "id");
        Page<ProjectEntity> projectPage = projectRepository.findAll(page);
        int index = 1;
        while (projectPage.hasContent()) {
            List<ProjectEntity> list = projectPage.getContent();
            for (ProjectEntity project : list) {
                project.setTodayReadCount(0);
                project.setTodayAppReadCount(0);
            }
            projectRepository.saveAll(list);
            projectPage = projectRepository.findAll(PageRequest.of(index++, 100, Sort.Direction.DESC, "id"));
        }
        logger.info("更新文章每日阅读量结束");
    }

    /**
     * 每小时执行更新阅读量任务
     */
    @Scheduled(initialDelay = 2000*60*60, fixedRate = 1000*60*60)
    public void updateSubjectReadCount()  {
        logger.info("=====每小时执行更新专题阅读量任务开始=====");
        String keyPre = RedisKeyPrefix.SUBJECTCOUNT+":viewCount:*";
        Set<String> keys = redisTemplate.keys(keyPre);
        //subjectID集合
        List<Integer> idList = new ArrayList<>();
        //subjecID和阅读量map
        Map<Integer,Integer> idNCountMap= new HashMap<>();
        if(!CollectionUtils.isEmpty(keys)){
            for (String key : keys) {
                Integer count = (Integer)redisTemplate.opsForValue().get(key);
                //等于0就不用更新
                if(count == null || count == 0){
                    continue;
                }
                //从key中解析获取文章ID
                String[] split = key.split(":");
                Integer articleId = Integer.valueOf(split[split.length-1]);
                idList.add(articleId);
                idNCountMap.put(articleId,count);
                //将redis的文章ID置空
                redisTemplate.opsForValue().set(key,count-count);
            }
            for (Integer id : idNCountMap.keySet()) {
                Integer count = idNCountMap.get(id);
                Optional<SubjectEntity> optionalSubject = subjectRepository.findById(id);
                if (optionalSubject.isPresent()) {
                    SubjectEntity subject = optionalSubject.get();
                    subject.setReadMount(subject.getReadMount()+count);
                    subjectRepository.save(subject);
                }
            }
        }
        logger.info("=====每小时执行更新专题阅读量任务结束=====");
    }


    @Scheduled(cron = "0 0 0 * * ?")
    public void updateTodayCount() {
        logger.info("清空当天访问量开始");
        String todayKey = RedisKeyPrefix.PROJECTVIEW+":today";
        Object todayCount = redisTemplate.opsForValue().get(todayKey);
        if(todayCount != null) {
            redisTemplate.opsForValue().set(todayKey, null);
        }
        logger.info("清空当天访问量结束");
    }

}
